#!/usr/bin/env python
# -*- coding: utf-8 -*-
from typing import TypeVar

from sqlalchemy import and_
from sqlalchemy.orm import Session

from app.common.page import PageParam
from app.models import User
from pydantic import BaseModel

from app.dao.base_dao import BaseDao
from app.db.base_class import Base
from app.models.bar import Bar
from app.models.constant import Constant
from app.models.favorite import Favorite
from app.models.instrument import Instrument
from app.models.user_setting import UserSetting
from app.schemas.bar import CandlestickQuery


class BarDao(BaseDao[Bar]):
    def __init__(self):
        super(BarDao, self).__init__()
        self.modelClass = Bar
        self.id = Bar.id

    def getCandlestick(self, db: Session, queryWrapper: CandlestickQuery, pageParam: PageParam):
        filters = {
            Bar.instrumentId == queryWrapper.instrumentId,
            Bar.frequency == queryWrapper.frequency,
            Bar.adjustFlag == queryWrapper.adjust
        }
        if queryWrapper.barDate:
            filters.add(Bar.barDate <= queryWrapper.barDate)
        if queryWrapper.start:
            filters.add(Bar.barDate >= queryWrapper.start)
        if queryWrapper.end:
            filters.add(Bar.barDate <= queryWrapper.end)
        bars = db.query(Bar.close, Bar.open, Bar.low, Bar.high, Bar.volume, Bar.amount, Bar.barDate,
                        Bar.preClose).filter(*filters) \
            .order_by(Bar.barDate.desc()) \
            .offset((pageParam.pageNum - 1) * pageParam.pageSize) \
            .limit(pageParam.pageSize).all()
        return bars

    def selectLast(self, db: Session, queryWrapper: CandlestickQuery, pageParam: PageParam):
        filters = {
            Instrument.marketType == queryWrapper.marketType
        }
        if queryWrapper.instrumentId:
            filters.add(Instrument.id == queryWrapper.instrumentId)
        result = db.query(Instrument.id, Favorite.id.label('favoriteId'), Instrument.name, Instrument.symbol, Bar.close, Bar.open, Bar.low, Bar.high,
                          Bar.volume, Bar.amount, Bar.barDate, Bar.preClose) \
            .select_from(Instrument) \
            .outerjoin(Favorite, and_(Instrument.id == Favorite.instrumentId,
                                      Favorite.userId == queryWrapper.userId)) \
            .outerjoin(Bar, and_(Instrument.id == Bar.instrumentId,
                                 Bar.barDate == queryWrapper.barDate,
                                 Bar.frequency == queryWrapper.frequency,
                                 Bar.adjustFlag == queryWrapper.adjust)) \
            .filter(*filters) \
            .order_by(Instrument.symbol.asc()) \
            .offset((pageParam.pageNum - 1) * pageParam.pageSize) \
            .limit(pageParam.pageSize) \
            .all()
        return result

    def selectLastCount(self, db: Session, queryWrapper: CandlestickQuery) -> int:
        return db.query(Instrument.id) \
            .filter(Instrument.id == Bar.instrumentId,
                    Instrument.marketType == queryWrapper.marketType,
                    Bar.barDate == queryWrapper.barDate,
                    Bar.frequency == queryWrapper.frequency,
                    Bar.adjustFlag == queryWrapper.adjust).count()


barDao = BarDao()
